import log from '../../../helpers/logger';
import { pushDiscordWebhook } from '../../../helpers/pushDiscordWebhook';
//import { validateLink } from '../../../helpers/dataValidation';

import {
  authorizedRouteHandler,
  ControllerMethodTypes,
  defaultRouteHandler,
} from '../../../../interfaces';
import { Request } from 'hyper-express';
import { showSelectedObjectKeys } from '../../../helpers/utilsJS';
import { vmc } from '../../../../../prisma/generated/uctoo';
import { setExCache } from '../../../helpers/redis';
import fs from 'fs';
import { defineOfficialAccountConfig, OfficialAccount, OpenPlatform, ServerRequest, FormData, defineOpenPlatformConfig } from 'node-easywechat';
import QRCode from 'qrcode';
import { queryAdminAppletsFromDatabase } from '../../../services/uctoo/admin_applet';
import { queryWechatopenAppletsFromDatabase } from '../../../services/uctoo/wechatopen_applet';
import path from 'path';
import { combineImages } from '../../../helpers/images';
import {
  getFirstWechatopenFromDatabase
} from '../../../services/uctoo/wechatopen';
import db from '../../../lib/db';
import DbCacher from '../../../lib/DbCacher';
  //#region AutoCreateCode
import {
  createVmc,
  deleteVmcFromDatabase,
  deleteMultiVmcFromDatabase,
  editVmcInDatabase,
  editMultiVmcInDatabase,
  getVmcFromDatabase,
  getVmcsFromDatabase,
  queryVmcsFromDatabase,
  countVmcs
} from '../../../services/uctoo/vmc';

class uctooVmcController {

  protected validateAndDestructureBody = async (
    req: Request,
    userId: string,
    actionType: ControllerMethodTypes
  ) => {
    const body = await req.json();
    const keysArray = Object.keys(body);       //如需自定义控制接收字段可在此定义，如['id','link','privacy_level','owner','description','group_id','stars'] ，默认接收所有提交字段
    const uctooVmc = showSelectedObjectKeys(body, keysArray) as vmc;
    uctooVmc.creator = userId;

    return uctooVmc;
  };
  public add: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const uctooVmc = await this.validateAndDestructureBody(
        req,
        user,
        ControllerMethodTypes.ADD
      );
      if (!uctooVmc) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

      const createdVmc = await createVmc(uctooVmc);
      if (!createdVmc) return res.status(500).json({ errno: "50001", errmsg: "database query failed" });

      res.status(200).json(createdVmc);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public edit: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      const { id,ids,force } = body;

      if(ids){
        const uctooVmc = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooVmc) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedVmc = await editMultiVmcInDatabase(uctooVmc, JSON.parse(ids), user);
        
        if (typeof editedVmc === 'object' && 'success' in editedVmc) {
          if (!editedVmc.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: editedVmc.reason,
              ...(editedVmc.vmcId && { vmcId: editedVmc.vmcId })
            });
          }
          return res.status(200).json(editedVmc.data);
        }
        
        res.status(200).json(editedVmc);
      }else{
        const uctooVmc = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooVmc) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedVmc = await editVmcInDatabase(uctooVmc, uctooVmc.id, user);
        
        if (typeof editedVmc === 'object' && 'success' in editedVmc) {
          if (!editedVmc.success) {
            return res.status(403).json({ errno: "40301", errmsg: editedVmc.reason });
          }
          return res.status(200).json(editedVmc.data);
        }
        res.status(200).json(editedVmc);
      }      
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public delete: authorizedRouteHandler = async (req, res) => {
    try {
      const body = await req.json();
      const { id,ids,force } = body;
      const user = res.locals.id.user;

      if(ids){
        const deletionResult = await deleteMultiVmcFromDatabase(JSON.parse(ids), force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: deletionResult.reason,
              ...(deletionResult.vmcId && { vmcId: deletionResult.vmcId })
            });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }else{
        const deletionResult = await deleteVmcFromDatabase(id, force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({ errno: "40301", errmsg: deletionResult.reason });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }

      res.status(200).json({ desc: '删除成功' });
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getSingle: authorizedRouteHandler = async (req, res) => {
    try {
      const { id } = req.params;
      const user = res.locals.id.user;

      const vmcFromDb = await getVmcFromDatabase(id, user);
      if (!vmcFromDb) {
        return res.status(404).json({ 
          errno: "40401", 
          errmsg: '未找到该实体或您没有权限访问' 
        });
      }

      res.status(200).json(vmcFromDb);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getMany: authorizedRouteHandler = async (req, res) => {
    try {
      const limit = parseInt(req.params.limit);
      const page = parseInt(req.params.page) || 0;
      const skip = parseInt(req.params.skip) || 0;
      const query = req.query;
      
      if (limit > 100) return res.status(400).json({ errno: "40002", errmsg: '请求数量不能超过100条' });
      if (isNaN(limit)) return res.status(400).json({ errno: "40003", errmsg: '请求数量必须是数字' });
      
      const user = res.locals.id.user;
      const totalCount = await countVmcs(user);
      
      if (query) {
        const vmcsFromDb = await queryVmcsFromDatabase(limit, page, skip, query, user);
        if (!vmcsFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount: totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          vmcs: vmcsFromDb
        });
      } else {
        const vmcsFromDb = await getVmcsFromDatabase(limit, skip, page, user);
        if (!vmcsFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount:totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          vmcs: vmcsFromDb
        });
      }


    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  //#endregion AutoCreateCode

  //第三方平台开发方式
  public wechatopenCreateQRCode: authorizedRouteHandler = async (req, res) => {
    const user = res.locals.id.user;
    const uctooVmc = await this.validateAndDestructureBody(
      req,
      user,
      ControllerMethodTypes.EDIT
    );
    // 取vmc数据
    const vmcFromDb = await getVmcFromDatabase(uctooVmc.id);
    if (!vmcFromDb) return res.status(404).end();
    // console.log('vmcFromDb:', vmcFromDb);
    const scene_str = vmcFromDb.vmc_no;
    // 取出 wechatopen_applet数据
    const params: Record<string, any> = {};
    params.filter = JSON.stringify({ status: 1 });
    const adminApplet = await queryAdminAppletsFromDatabase(1, 0, 0, params);
    if (!adminApplet) return res.status(404).end();
    //log.info('adminApplet:', adminApplet);
    const waparams: Record<string, any> = {};
    waparams.filter = JSON.stringify({ appid: adminApplet[0].appid });
    const wechatApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, waparams);
    if (!wechatApplet) return res.status(404).end();
    //log.info('wechatApplet:', wechatApplet);
    const targetPath = path.resolve('assets/qrcode')
    try {

      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });

      log.info({ info: 'wechatopensFromDb', wechatopenFromDb });


      const wechatopenConfig = defineOpenPlatformConfig({
        // 微信公众号的 app key
        app_id: wechatopenFromDb['appid'],
        // 微信公众号的 app secret
        secret: wechatopenFromDb['appsecret'],
        // 微信公众号的 token
        token: wechatopenFromDb['token'],
        // EncodingAESKey
        aes_key: wechatopenFromDb['encoding_aes_key'],

      })
      const wxopen = new OpenPlatform(wechatopenConfig);
      // 替换缓存实例
      let Dbcacher = new DbCacher(db);
      wxopen.setCache(Dbcacher);
      const body = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);

      const params: Record<string, any> = {};
      params.filter = JSON.stringify({ appid: adminApplet[0].appid });
      const wechatopenApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, params);
      const refreshToken = wechatopenApplet[0].authorizer_refresh_token;
      //获取sdk中初始化的公众号应用
      const oaApp = await wxopen.getOfficialAccountWithRefreshToken(adminApplet[0].appid, refreshToken);


      const client = wxopen.getClient();
      const wxserver = wxopen.getServer();


      const qrbody = { "action_name": "QR_LIMIT_STR_SCENE", "action_info": { "scene": { scene_str } } };

      const oaAppclient = oaApp.getClient();
      const response = await oaAppclient.postJson("cgi-bin/qrcode/create", qrbody)
      const data = response.toObject()

      if (!data.errcode || data.errcode == '0') {

        // 保存到本地目录下
        const opts = {
          errorCorrectionLevel: 'H',
          type: 'image/png',
          margin: 1,
          width: 660 // 设置图片的宽度
        }
        const qrCodeImage = await QRCode.toDataURL(data.url, opts);
        const base64Data = qrCodeImage.replace(/^data:image\/\w+;base64,/, '')
        const bytesData = Buffer.from(base64Data, "base64");
        const foregroundPath = `${targetPath}/${scene_str}.png`
        if (!fs.existsSync(targetPath)) {
          try {
            fs.mkdirSync(targetPath, { recursive: true });
          } catch (err) {
            console.error(err);
          }
        }
        fs.writeFileSync(foregroundPath, bytesData);
        // 合成图片
        //先去掉背景图
        /*
        const backgroundPath = `${targetPath}/background.jpg`;
        const outputPath = `${targetPath}/${scene_str}_out.jpg`
        const rs = await combineImages(backgroundPath, foregroundPath, outputPath);  */
        // 将url保存到vmc表
        const domain = process.env.API_URL;
        const url = `${domain}/assets/qrcode/${scene_str}.png`  // `${domain}/assets/qrcode/${scene_str}_out.jpg`  //带背景图的输出路径
        await editVmcInDatabase({ cover_image: url }, uctooVmc.id)
        res.status(200).json({
          url: url,
        });
      }
      res.status(200).json(data);
    } catch (e) {
      console.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }
  }

  public createQRCode: authorizedRouteHandler = async (req, res) => {
    const user = res.locals.id.user;//"505cf909-5e0e-4dde-b215-74274d2cc548";//
    const uctooVmc = await this.validateAndDestructureBody(
      req,
      user,
      ControllerMethodTypes.EDIT
    );
    // 取vmc数据
    const vmcFromDb = await getVmcFromDatabase(uctooVmc.id);
    if (!vmcFromDb) return res.status(404).end();
    // console.log('vmcFromDb:', vmcFromDb);
    const scene_str = vmcFromDb.vmc_no;
    // 取出 wechatopen_applet数据
    const params: Record<string, any> = {};
    params.filter = JSON.stringify({ status: 1 });
    const adminApplet = await queryAdminAppletsFromDatabase(1, 0, 0, params);
    if (!adminApplet) return res.status(404).end();
    //log.info('adminApplet:', adminApplet);
    const waparams: Record<string, any> = {};
    waparams.filter = JSON.stringify({ appid: adminApplet[0].appid });
    const wechatApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, waparams);
    if (!wechatApplet) return res.status(404).end();
    //log.info('wechatApplet:', wechatApplet);
    const targetPath = path.resolve('assets/qrcode')
    try {
      const oa = defineOfficialAccountConfig({
        // 微信公众号的 app key
        app_id: wechatApplet[0].appid, //'wx2cdf8e0dffd4b2b2',
        // 微信公众号的 app secret
        secret: wechatApplet[0].appsecret,// '13be9d444b156f90fd175489fcb29c7c',
        // 微信公众号的 token
        token: wechatApplet[0].token,// 'uctoo',
        // EncodingAESKey
        aes_key: wechatApplet[0].aeskey,// 'uxo7tdM2iF5PQiQSLNfpdDD4k4X6ajVYJxEIxtxDYLg',
        // 网页授权认证
        oauth: {
          // 网页授权类型
          scope: 'snsapi_userinfo',
          // 网页授权回调地址，完整的URL
          redirect_url: 'https://demoapi.uctoo.com/wxlogin/callback'
        },
      })
      const body = { "action_name": "QR_LIMIT_STR_SCENE", "action_info": { "scene": { scene_str } } };
      const wxapp = new OfficialAccount(oa);
      const client = wxapp.getClient();
      const response = await client.postJson("cgi-bin/qrcode/create", body)
      const data = response.toObject()

      if (!data.errcode || data.errcode == '0') {

        // 保存到本地目录下
        const opts = {
          errorCorrectionLevel: 'H',
          type: 'image/png',
          margin: 1,
          width: 660 // 设置图片的宽度
        }
        const qrCodeImage = await QRCode.toDataURL(data.url, opts);
        const base64Data = qrCodeImage.replace(/^data:image\/\w+;base64,/, '')
        const bytesData = Buffer.from(base64Data, "base64");
        const foregroundPath = `${targetPath}/${scene_str}.png`
        if (!fs.existsSync(targetPath)) {
          try {
            fs.mkdirSync(targetPath, { recursive: true });
          } catch (err) {
            console.error(err);
          }
        }
        fs.writeFileSync(foregroundPath, bytesData);
        // 合成图片
        const backgroundPath = `${targetPath}/background.jpg`;
        const outputPath = `${targetPath}/${scene_str}_out.jpg`
        const rs = await combineImages(backgroundPath, foregroundPath, outputPath);
        // 将url保存到vmc表
        const domain = process.env.API_URL;
        const url = `${domain}/assets/qrcode/${scene_str}_out.jpg`
        await editVmcInDatabase({ cover_image: url }, uctooVmc.id)
        res.status(200).json({
          url: url,
        });
      }
      res.status(200).json(data);
    } catch (e) {
      console.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }
  }

   //第三方平台开发方式，生成扫码登录二维码，不限数量带参二维码
   public wechatopenCreateLoginQRCode: defaultRouteHandler = async (req, res) => {
    
    // 取出 wechatopen_applet数据
    const params: Record<string, any> = {};
    params.filter = JSON.stringify({ status: 1 });
    const adminApplet = await queryAdminAppletsFromDatabase(1, 0, 0, params);
    if (!adminApplet) return res.status(404).end();
    //log.info('adminApplet:', adminApplet);
    const waparams: Record<string, any> = {};
    waparams.filter = JSON.stringify({ appid: adminApplet[0].appid });
    const wechatApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, waparams);
    if (!wechatApplet) return res.status(404).end();
    try {

      const wechatopenFromDb = await getFirstWechatopenFromDatabase({ status: 1 }, { id: 'desc' });
      const wechatopenConfig = defineOpenPlatformConfig({
        // 微信公众号的 app key
        app_id: wechatopenFromDb['appid'],
        // 微信公众号的 app secret
        secret: wechatopenFromDb['appsecret'],
        // 微信公众号的 token
        token: wechatopenFromDb['token'],
        // EncodingAESKey
        aes_key: wechatopenFromDb['encoding_aes_key'],

      })
      const wxopen = new OpenPlatform(wechatopenConfig);
      // 替换缓存实例
      let Dbcacher = new DbCacher(db);
      wxopen.setCache(Dbcacher);
      const body = await req.text();
      const reqbody = await req.json();
      const { client_id } = reqbody;
      log.info('client_id:', client_id);

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxopen.setRequest(request);

      const params: Record<string, any> = {};
      params.filter = JSON.stringify({ appid: adminApplet[0].appid });
      const wechatopenApplet = await queryWechatopenAppletsFromDatabase(1, 0, 0, params);
      const refreshToken = wechatopenApplet[0].authorizer_refresh_token;
      //获取sdk中初始化的公众号应用
      const oaApp = await wxopen.getOfficialAccountWithRefreshToken(adminApplet[0].appid, refreshToken);

      const client = wxopen.getClient();
      const wxserver = wxopen.getServer();
      const scene_str = `login_client_id_${client_id}`;

      const qrbody = { "action_name": "QR_STR_SCENE", "action_info": { "scene": {"scene_str": scene_str} } ,"expire_seconds": 600 };

      const oaAppclient = oaApp.getClient();
      const response = await oaAppclient.postJson("cgi-bin/qrcode/create", qrbody)
      const data = response.toObject()

      if (!data.errcode || data.errcode == '0') {
        const opts = {
          errorCorrectionLevel: 'H',
          type: 'image/png',
          margin: 1,
          width: 660 // 设置图片的宽度
        }
        const qrCodeImage = await QRCode.toDataURL(data.url, opts);
        res.status(200).json({
          loginQrcode: qrCodeImage,
        });
      }
      res.status(200).json(data);
    } catch (e) {
      console.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }
  }

}

export default uctooVmcController;
